#lang scribble/doc


@(require scribble/manual)
@(require (except-in rosetta section))


@title{Rosetta}
@declare-exporting[Rosetta]


@section{Coords}

Coords represent spatial coordinates and they are used in a variety of
situations, for example, to specify the location of geometric shapes.

Coords can be Cartesian, cylindrical, polar or spherical, and there
are many operations to manipulate coordinates, such as, addition,
subtraction, dot product, cross product, and so on.

There are several alternative names for the functions defined for
coordinates, depending on the language you are using.

Example 1: a sphere of radius @racket[10], located at @racket[(1 2
3)], using Cartesian coordinates:
@codeblock{(sphere (xyz 1 2 3) 10)}

Example 2: a sphere of radius @racket[10], located at @racket[(0 1
0)], using polar coordinates:
@codeblock{(sphere (pol 1 pi/2) 10)}

Example 3: using lang @racket[rosetta-racket] and alternative names:
@codeblock{
#lang rosetta-racket

(define (plus-1 c r)
  (sphere (+x c 1) r))
}

Example 4: definition of the @racket[rotate] constructor that rotates
a shape based on the begin and end coordinates.
@codeblock{
(define (rotate c1 c2 shape)
  (let ((n (if (< (collinearity-c c1 c2) 0)
               (collinear-cross-c c1)
               (cross-c c1 c2))))
    (rotate (angle-c c1 c2) n shape)))
}


@subsection{Cartesian}

@defproc[(xyz (x number?) (y number?) (z number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, where
@racket[x] is the length in the X-axis, @racket[y] is the length in
the Y-axis, and @racket[z] is the length in the Z-axis.
}

@defproc*[(((xy (x number?) (y number?)) coord?)
           ((xy (c coord?) (x number?) (y number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

Equivalent to @itemlist{@item{@racket[(xyz x y 0)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[z] taken from @racket[c].

Equivalent to @itemlist{@item{@racket[(x y (xyz-z c))]}}
}

@defproc*[(((yz (y number?) (z number?)) coord?)
           ((yz (c coord?) (y number?) (z number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

Equivalent to @itemlist{@item{@racket[(xyz 0 y z)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[x] taken from @racket[c].

Equivalent to @itemlist{@item{@racket[(xyz (xyz-x c) y z)]}}
}

@defproc*[(((xz (x number?) (z number?)) coord?)
           ((xz (c coord?) (x number?) (z number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

@itemlist{@item{Equivalent to @racket[(xyz x 0 z)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[y] taken from @racket[c]

Equivalent to @itemlist{@item{@racket[(xyz x (xyz-y c) z)]}}
}

@defproc*[(((x (x number?)) coord?)
           ((x (c coord?) (x number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

Equivalent to @itemlist{@item{@racket[(xyz x 0 0)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[y] and @racket[z] taken from @racket[c].

Equivalent to @itemlist{@item{@racket[(xyz x (xyz-y c) (xyz-z c))]}}
}
                                                
@defproc*[(((y (y number?)) coord?)
           ((y (c coord?) (y number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

Equivalent to @itemlist{@item{@racket[(xyz 0 y 0)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[x] and @racket[z] taken from @racket[c]

Equivalent to @itemlist{@item{@racket[(xyz (xyz-x c) y (xyz-z c))]}}
}
                                                
@defproc*[(((z (z number?)) coord?)
           ((z (c coord?) (z number?)) coord?))]{
First version: creates a @racket[coord?] using Cartesian coordinates.

Equivalent to @itemlist{@item{@racket[(xyz 0 0 z)]}}

Second version: creates a @racket[coord?] using Cartesian coordinates
with @racket[x] and @racket[y] taken from @racket[c]

Equivalent to @itemlist{@item{@racket[(xyz (xyz-x c) (xyz-y c) z)]}}
}
                                                
@defproc[(xyz-x (c coord?)) number?]{
Returns the Cartesian @racket[x] value of @racket[c].
}

@defproc[(xyz-y (c coord?)) number?]{
Returns the Cartesian @racket[y] value of @racket[c].
}

@defproc[(xyz-z (c coord?)) number?]{
Returns the Cartesian @racket[z] value of @racket[c].
}

@defproc[(xyz-r (c coord?)) number?]{
Returns the length of @racket[c].
}


@subsection{Cylindrical}

@defproc[(cyl (rho distance?) (phi number?) (z number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates, where
@racket[rho] is the distance of the projection in the XY-plane,
@racket[phi] is the angle in the XY-plane with the X-axis, and
@racket[z] is equivalent to the Cartesian @racket[z].
}

@defproc*[(((rho (rho number?)) coord?)
           ((rho (c coord?) (rho number?)) coord?))]{
First version: creates a @racket[coord?] using cylindrical
coordinates.

Equivalent to @itemlist{@item{@racket[(cyl rho 0 0)]}}

Second version: creates a @racket[coord?] using cylindrical
coordinates with @racket[phi] and @racket[z] taken from @racket[c].

Equivalent to @itemlist{@item{@racket[(cyl c rho (cyl-phi c) (cyl-z c))]}}
                        
In lang @racket[rosetta-racket], use @racket[cyl-ρ] instead.
}

@defproc*[(((phi (phi number?)) coord?)
           ((phi (c coord?) (phi number?)) coord?))]{
First version: creates a @racket[coord?] using cylindrical
coordinates.

Equivalent to @itemlist{@item{@racket[(cyl 0 phi 0)]}}

Second version: creates a @racket[coord?] using cylindrical
coordinates with @racket[rho] and @racket[phi] taken from @racket[c].

Equivalent to @itemlist{@item{@racket[(cyl c (cyl-rho c) phi (cyl-z c))]}}
                        
In lang @racket[rosetta-racket], use @racket[cyl-ρ] instead.
}

@defproc[(cyl-phi (c coord?)) number?]{
Returns the cylindrical @racket[phi] value of @racket[c].

Equivalent @itemlist{@item{@racket[sph-phi]}}

In lang @racket[rosetta-racket], use @racket[cyl-φ] instead.
}

@defproc[(cyl-z (c coord?)) number?]{
Returns the cylindrical @racket[z] value of @racket[c].

Equivalent to @itemlist{@item{@racket[xyz-z]}}
}


@subsection{Polar}

Polar coordinates are a particular case of cylindrical coordinates,
where the value of @racket[z] is @racket[0].

@defproc[(pol (rho distance?) (phi number?)) coord?]{
Creates a @racket[coord?] using polar coordinates. 

Equivalent to @itemlist{@item{@racket[(cyl rho phi 0)]}}
}

@defproc[(pol-rho (c coord?)) distance?]{
Returns the polar @racket[rho] value of @racket[c].

Equivalent to @itemlist{@item{@racket[cyl-rho] but the cylindrical
@racket[z] of @racket[c] is @racket[0]}}

In lang @racket[rosetta-racket], use @racket[pol-ρ] instead.
}

@defproc[(pol-phi (c coord?)) number?]{
Returns the polar @racket[phi] value of @racket[c].

Equivalent to @itemlist{@item{@racket[cyl-phi] but the cylindrical
@racket[z] value of @racket[c] is @racket[0]}}

In lang @racket[rosetta-racket], use @racket[pol-φ] instead.
}


@subsection{Spherical}

@defproc[(sph (r distance?) (phi number?) (th number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates, where
@racket[r] is the distance, @racket[phi] is the angle in the XY-plane
with the X-axis, and @racket[th] is the angle in the vertical plane
defined by @racket[phi] with the Z-axis.
}

@defproc[(sph-r (c coord?)) distance?]{
Returns the spherical @racket[r] value of @racket[c].

Equivalent to @itemlist{@item{@racket[xyz-r]}}
}

@defproc[(sph-phi (c coord?)) number?]{
Returns the spherical @racket[phi] value of @racket[c].

Equivalent to @itemlist{@item{@racket[cyl-phi]}}
                      
In lang @racket[rosetta-racket], use @racket[sph-φ] instead.
}

@defproc[(sph-th (c coord?)) number?]{
Returns the spherical @racket[th] value of @racket[c].
                      
In lang @racket[rosetta-racket], use @racket[sph-θ] instead.
}


@subsection{Constants}

@defidform[u0]{
A convenience name for the origin.

Equivalent to @itemlist{@item{@racket[(xyz 0 0 0)]}}
}


@defidform[ux]{
A convenience name for the X-axis unit vector.

Equivalent to @itemlist{@item{@racket[(xyz 1 0 0)]}}
}

@defidform[uy]{
A convenience name for the Y-axis unit vector.

Equivalent to @itemlist{@item{@racket[(xyz 0 1 0)]}}
}

@defidform[uz]{
A convenience name for the Z-axis unit vector.

Equivalent to @itemlist{@item{@racket[(xyz 0 0 1)]}}
}


@defidform[uxy]{
A convenience name for the addition of @racket[ux] and @racket[uy].

Equivalent to @itemlist{@item{@racket[(xyz 1 1 0)]}}
}

@defidform[uyz]{
A convenience name for the addition of @racket[uy] and @racket[uz].

Equivalent to @itemlist{@item{@racket[(xyz 0 1 1)]}}
}

@defidform[uxz]{
A convenience name for the addition of @racket[ux] and @racket[uz].

Equivalent to @itemlist{@item{@racket[(xyz 1 0 1)]}}
}

@defidform[uxyz]{
A convenience name for the addition of @racket[ux], @racket[uy] and
@racket[uz].

Equivalent to @itemlist{@item{@racket[(xyz 1 1 1)]}}
}


@subsection{Predicates}

@defproc[(is-coord (c any/c)) boolean?]{
Tests if @racket[c] is a @racket[coord?].
         
In lang @racket[rosetta-racket], use @racket[coord?] instead.
}

@defproc[(is-u0 (c any/c)) boolean?]{
Tests if @racket[c] is a @racket[coord?] and if it is the origin.
         
In lang @racket[rosetta-racket], use @racket[u0?] instead.
}


@subsection{Operations}

@defproc*[(((eq-c (c1 coord?) (c2 coord?)) boolean?)
           ((eq-c (c1 coord?) (c2 coord?) (threshold-d (not/c negative?))) boolean?))]{
First version: tests if @racket[c1] and @racket[c2] are
@racket[equal?].

Second version: tests if @racket[c1] and @racket[c2] are
@racket[equal?] given the @racket[threshold-d].

If @racket[(= threshold-d 0)] then the second version is equivalent to
the first.

In lang @racket[rosetta-racket], use @racket[=c] instead.
}

@defproc*[(((add-c (c1 coord?) (c2 coord?)) coord?)
           ((add-c (c1 coord?) (c2 coord?) ...) coord?))]{
First version: creates a @racket[coord?] that results from adding
@racket[c1] and @racket[c2].

Second version: creates a @racket[coord?] that results from adding
@racket[c1], @racket[c2] and @racket[...].

In lang @racket[rosetta-racket], use @racket[+c] instead.
}

@defproc*[(((sub-c (c1 coord?) (c2 coord?)) coord?)
           ((sub-c (c1 coord?) (c2 coord?) ...) coord?))]{
First version: creates a @racket[coord?] that results from subtracting
@racket[c1] and @racket[c2].

Second version: creates a @racket[coord?] that results from
subtracting @racket[c1], @racket[c2] and @racket[...].

In lang @racket[rosetta-racket], use @racket[-c] instead.
}

@defproc[(dot-c (c1 coord?) (c2 coord?)) number?]{
Creates a @racket[coord?] that is the dot product of @racket[c1] and
@racket[c2].

In lang @racket[rosetta-racket], use @racket[.c] instead.
}

@defproc[(cross-c (c1 coord?) (c2 coord?)) coord?]{
Creates a @racket[coord?] that is the cross product of @racket[c1] and
@racket[c2].

In other words, it creates a @racket[coord?] that is perpendicular to
both @racket[c1] and @racket[c2].

In lang @racket[rosetta-racket], use @racket[xc] instead.
}

@defproc[(collinear-cross-c (c coord?)) coord?]{
Creates a @racket[coord?] that is perpendicular @racket[c].
          
In lang @racket[rosetta-racket], use @racket[collinear-xc] instead.
}

@defproc*[(((angle-c (c1 coord?) (c2 coord?)) number?)
           ((angle-c (c1 coord?) (c2 coord?) (normal coord?)) number?))]{
First version: returns the shortest angle between @racket[c1] and
@racket[c2].

Second version: returns the angle between @racket[c1] and @racket[c2],
where @racket[normal] is the normal vector of the direction of the
angle, thus allowing angles greater than @racket[pi] as result.

In lang @racket[rosetta-racket], use @racket[</c] instead.

For example,
@racket[(</c (xyz 1 0 0) (xyz 1 1 0))] is @racket[pi/4] and
@racket[(</c (xyz 1 0 0) (xyz 1 1 0) (xyz 0 0 -1))] is @racket[(- 2pi
pi/4)].
}

@defproc[(collinearity-c (c1 coord?) (c2 coord?)) number?]{
Returns the collinearity factor @racket[r] between @racket[c1] and
@racket[c2], such that @racket[(=c (* c1 r) c2)].

In lang @racket[rosetta-racket], use @racket[//c] instead.
}

@defproc*[(((mult-c (c coord?) (r number?)) coord?)
           ((mult-c (r number?) (c coord?)) coord?))]{
Both versions create a @racket[coord?] that results from the scalar
multiplication of @racket[c] by @racket[r].

In lang @racket[rosetta-racket], use @racket[*c] instead.
}


@defproc[(distance (c1 coord?) (c2 coord?)) number?]{
Returns the distance between @racket[c1] and @racket[c2].

Equivalent to @itemlist{@item{(xyz-r (sub-c c1 c2))}}
}

@defproc[(midcoord (c1 coord?) (c2 coord?)) number?]{
Creates a @racket[coord?] that is halfway between @racket[c1] and
@racket[c2].

Equivalent to @itemlist{@item{(add-c c1 (mult-c (sub-c c2 c1) 1/2))}}
}

@defproc[(norm (c coord?)) number?]{
Creates a @racket[coord?] @racket[d], such that @racket[c] and
@racket[n] are collinear, and @racket[(= (xyz-r d) 1)].

In other words, creates a @racket[coord?] that is @racket[c]
normalized.

Equivalent to @itemlist{@item{@racket[(mult-c c (/ (xyz-r c)))]}}
}

@defproc[(symmetric (c coord?)) coord?]{
Creates a @racket[coord?] @racket[d], such that @racket[c] and
@racket[n] are collinear, and @racket[(eq-c (*c c -1) d)].
}


@defproc[(add-x-c (c coord?) (n number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[y] and @racket[z] are taken from @racket[c], and @racket[x]
results from the addition of the @racket[x] taken from @racket[c] with
@racket[n].

Equivalent to @itemlist{@item{@racket[(x c (+ (xyz-x c) n))]}}

In lang @racket[rosetta-racket], use @racket[+x] instead.
}

@defproc[(add-y-c (c coord?) (n number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[x] and @racket[z] are taken from @racket[c], and @racket[y]
results from the addition of the @racket[y] taken from @racket[c] with
@racket[n].

Equivalent to @itemlist{@item{@racket[(y c (+ (xyz-y c) r))]}}

In lang @racket[rosetta-racket], use @racket[+y] instead.
}

@defproc[(add-z-c (c coord?) (n number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[x] and @racket[y] are taken from @racket[c], and @racket[z]
results from the addition of the @racket[z] taken from @racket[c] with
@racket[n].

Equivalent to @itemlist{@item{@racket[(z c (+ (xyz-z c) r))]}}

In lang @racket[rosetta-racket], use @racket[+z] instead.
}

@defproc[(add-xy-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[z] is taken from @racket[c], and both @racket[x] and
@racket[y] result from the addition of @racket[x] and @racket[y] taken
from @racket[c] with parameters @racket[x] and @racket[y],
respectively.

Equivalent to @racket[(xy c (+ (xyz-x c) x) (+ (xyz-y c) y))].

In lang @racket[rosetta-racket], use @racket[+xy] instead.
}

@defproc[(add-yz-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[x] is taken from @racket[c], and both @racket[y] and
@racket[z] result from the addition of @racket[y] and @racket[z] taken
from @racket[c] with parameters @racket[x] and @racket[y],
respectively.

Equivalent to @racket[(yz c (+ (xyz-y c) x) (+ (xyz-z c) y))].

In lang @racket[rosetta-racket], use @racket[+yz] instead.
}

@defproc[(add-xz-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, such that
@racket[y] is taken from @racket[c], and both @racket[x] and
@racket[z] result from the addition of @racket[x] and @racket[z] taken
from @racket[c] with parameters @racket[x] and @racket[y],
respectively.

Equivalent to @racket[(xz c (+ (xyz-x c) x) (+ (xyz-z c) y))].

In lang @racket[rosetta-racket], use @racket[+xz] instead.
}

@defproc[(add-xyz-c (c coord?) (x number?) (y number?) (z number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that @racket[x], @racket[y] and @racket[z] values result from the addition of @racket[x], @racket[y] and @racket[z] values of @racket[c]
with parameters @racket[x], @racket[y] and @racket[z], respectively.

Equivalent to @racket[(xyz c (+ (xyz-x c) x) (+ (xyz-y c) y) (+ (xyz-z c) z))].

In lang @racket[rosetta-racket], use @racket[+xyz] instead.
}

@defproc[(add-cyl-c (c coord?) (rho number?) (phi number?) (z number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates, such that
@racket[rho], @racket[phi] and @racket[z] values result from the
addition of @racket[rho], @racket[phi] and @racket[z] values of
@racket[c] with parameters @racket[rho], @racket[phi] and @racket[z],
respectively.

Equivalent to @racket[(cyl (+ (cyl-rho c) rho) (+ (cyl-phi c) phi) (+ (cyl-z c) z))].

In lang @racket[rosetta-racket], use @racket[+cyl] instead.
}

@defproc[(add-rho-c (c coord?) (rho number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates, such that
@racket[rho] results from the addition of @racket[rho] taken from
@racket[c] with parameter @racket[rho].

Equivalent to @racket[(+cyl c rho 0 0)].
}

@defproc[(add-phi-c (c coord?) (phi number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates, such that
@racket[phi] results from the addition of @racket[phi] taken from
@racket[c] with parameter @racket[phi].

Equivalent to @racket[(+cyl c 0 phi 0)].
}

@defproc[(add-pol-c (c coord?) (rho number?) (phi number?)) coord?]{
Creates a @racket[coord?] using polar coordinates, such that
@racket[rho] and @racket[phi] result from the addition of @racket[rho]
and @racket[phi] taken from @racket[c] with parameters @racket[rho]
and @racket[phi], respectively.

Equivalent to @itemlist{@item{@racket[(pol (+ (pol-rho c) rho) (+ (pol-phi c) phi))]}@item{@racket[(+cyl c (+ (pol-rho c) rho) (+ (pol-phi c) phi) 0)]}}

In lang @racket[rosetta-racket], use @racket[+pol] instead.
}

@defproc[(add-sph-c (c coord?) (r number?) (phi number?) (th number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates, such that
@racket[r], @racket[phi] and @racket[th] result from the addition of
@racket[rho], @racket[phi] and @racket[th] taken from @racket[c] with
parameters @racket[rho], @racket[phi] and @racket[th], respectively.

Equivalent to @racket[(sph (+ (sph-r c) rho) (+ (sph-phi c) phi) (+ (sph-th c) th))].

In lang @racket[rosetta-racket], use @racket[+sph] instead.
}

@defproc[(add-r-c (c coord?) (r number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates, such that
@racket[r] results from the addition of @racket[r] taken from
@racket[c] with parameter @racket[r].

Equivalent to @racket[(add-sph-c c r 0 0)].
}

@defproc[(add-th-c (c coord?) (th number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates, such that
@racket[th] results from the addition of @racket[th] taken from
@racket[c] with parameter @racket[th].

Equivalent to @racket[(add-sph-c c 0 0 th)].
}

@defproc[(list-of-coord (c coord?)) (listof number?)]{
Creates a @racket[list?] whose elements are the Cartesian values of
@racket[c].

Equivalent to @racket[(list (xyz-x c) (xyz-y c) (xyz-z c))].

In lang @racket[rosetta-racket], use @racket[list<-coord] instead.
}

@defproc[(vector-of-coord (c coord?)) (vectorof number?)]{
Creates a @racket[vector?] whose elements are the Cartesian values of
@racket[c].

Equivalent to @racket[(vector (xyz-x c) (xyz-y c) (xyz-z c))].

In lang @racket[rosetta-racket], use @racket[vector<-coord] instead.
}

@defproc[(coord-of-vector (v (vectorof number?))) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, where
@racket[x], @racket[y] and @racket[z] are the elements of @racket[v].

Equivalent to @racket[(apply xyz (vector->list v))].

In lang @racket[rosetta-racket], use @racket[coord<-vector] instead.
}